<?php

namespace App\Console\Commands;

use App\Models\Base\PayAnalyze;
use App\Service\AccountService;
use App\Service\ChannelService;
use App\Service\OrderService;
use App\Service\PlayerService;
use App\Service\ServerService;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class FetchPayLTV extends CommandBase
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'fetch:ltv {dateTime?}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '付费分析LTV统计';

    /**数据模型
     * @var PayAnalyze
     */
    protected $model;

    /**统计日期集合
     * @var array
     */
    protected $days;

    protected $gapDay = 0;

    /**
     * Create a new command instance.
     */
    public function __construct()
    {
        parent::__construct();
        $this->model = new PayAnalyze();
        $this->days = [
            1 => 'two_day_ltv',
            2 => 'three_day_ltv',
            3 => 'four_day_ltv',
            4 => 'five_day_ltv',
            5 => 'six_day_ltv',
            6 => 'seven_day_ltv',
            14 => 'fifteen_day_ltv',
            29 => 'thirty_day_ltv',
        ];
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $dateTime = $this->argument('dateTime');
        $nowTimestamp = $this->todayTimestamp;
        if ($dateTime) {
            $this->today = $dateTime;
            $this->todayTimestamp = strtotime($dateTime);
            $this->yesterdayTimestamp = $this->todayTimestamp - self::DAY_TIMESTAMP;
            $this->yesterday = date('Y-m-d', $this->yesterdayTimestamp);
            $this->gapDay = ($nowTimestamp - $this->todayTimestamp) / self::DAY_TIMESTAMP;
        }

        try {
            //全平台统计
            $this->platformAll();
            //渠道统计
            $this->channelStat();
            //区服统计
            $this->serverStat();
        } catch (\Exception $e) {
            Log::error('统计付费分析LTV错误');
            dd($e);
        }
    }

    /**
     * 区服统计
     */
    protected function serverStat()
    {
        $server_ids = ServerService::serverIds();
        if ($server_ids->isEmpty()) {
            return false;
        }
        foreach ($server_ids as $server_id) {
            setDB($server_id);
            $this->model = new PayAnalyze();
            $this->model->type = self::STAT_TYPE_SERVER;
            $this->model->server_id = $server_id;
            $this->model->date_time = $this->yesterday;
            //新增角色数量
            $new_role = PlayerService::getSignPlayer($this->yesterdayTimestamp, $this->todayTimestamp);
            $new_role_count = $new_role->count();
            if (!$new_role_count) {
                $this->model->new_users =
                $this->model->first_day_amount =
                $this->model->one_day_ltv =
                $this->model->total_amount = 0;
            } else {
                $role_ids = $new_role->pluck('id')->all();
                //昨日订单金额
                $orders = OrderService::getRoleOrders($role_ids,$this->yesterdayTimestamp, $this->todayTimestamp);
                $order_amount = $orders->pluck('amount')->sum();
                $this->model->new_users = $new_role_count;
                $this->model->first_day_amount = $this->model->total_amount = $order_amount;
                $this->model->one_day_ltv =$order_amount / $new_role_count;
            }
            $this->model->save();

            //更新往日数据
            foreach ($this->days as $day => $ltv_key) {
                $dateTimes = [];
                $dateTimes[] = $this->yesterday;
                for ($i = 1; $i <= $day; ++$i) {
                    $dateTimes[] = date('Y-m-d', $this->yesterdayTimestamp - (self::DAY_TIMESTAMP * $i));
                }
                $day += $this->gapDay;
                $ltv_yesterday = Carbon::parse($day + 1 .' days ago');
                $analyze_result = PayAnalyze::where('date_time', $ltv_yesterday->toDateString())
                    ->where('server_id', $server_id)->where('type', self::STAT_TYPE_SERVER)->first();
                if (!$analyze_result) {
                    continue;


                }
                $this->updateAnalyze($analyze_result, $dateTimes, self::STAT_TYPE_SERVER, $ltv_key, $server_id);
            }
        }
    }

    /**
     * 渠道统计
     */
    protected function channelStat()
    {
        $channel_ids = ChannelService::getChannels();
        if ($channel_ids->isEmpty()) {
            return false;
        }
        foreach ($channel_ids as $channel_id => $platform_id) {
            $this->model = new PayAnalyze();
            $this->model->type = self::STAT_TYPE_CHANNEL;
            $this->model->channel_id = $channel_id;
            $this->model->date_time = $this->yesterday;
            //昨日注册人数
            $new_users = ChannelService::registerUsers($this->yesterdayTimestamp, $this->todayTimestamp, $channel_id);
            $new_user_count = $new_users->count();

            if (!$new_user_count) {
                $this->model->new_users =
                $this->model->first_day_amount =
                $this->model->one_day_ltv =
                $this->model->total_amount = 0;
            } else {
                //昨日订单金额
                $new_user_ids = $new_users->pluck('ac_id')->all();
                //昨日订单金额
                $orders = OrderService::getUserOrders($new_user_ids,$this->yesterdayTimestamp, $this->todayTimestamp);
                $order_amount = $orders->pluck('amount')->sum();
                $this->model->new_users = $new_user_count;
                $this->model->first_day_amount = $this->model->total_amount = $order_amount;
                $this->model->one_day_ltv = $order_amount / $new_user_count;
            }
            $this->model->save();
            //更新往日数据
            foreach ($this->days as $day => $ltv_key) {
                $dateTimes = [];
                $dateTimes[] = $this->yesterday;
                for ($i = 1; $i <= $day; ++$i) {
                    $dateTimes[] = date('Y-m-d', $this->yesterdayTimestamp - (self::DAY_TIMESTAMP * $i));
                }
                $day += $this->gapDay;
                $ltv_yesterday = Carbon::parse($day + 1 .' days ago');
                $analyze_result = PayAnalyze::where('date_time', $ltv_yesterday->toDateString())
                    ->where('channel_id', $channel_id)->where('type', self::STAT_TYPE_CHANNEL)->first();
                if (!$analyze_result) {
                    continue;
                }
                $this->updateAnalyze($analyze_result, $dateTimes, self::STAT_TYPE_CHANNEL, $ltv_key, null, $channel_id);
            }
        }
    }

    /**
     * 全平台统计
     */
    protected function platformAll()
    {
        $this->model->type = self::STAT_TYPE_PLATFORM;
        $this->model->date_time = $this->yesterday;
        //昨日注册人数
        $new_users = AccountService::signNumber($this->yesterdayTimestamp, $this->todayTimestamp);
        $new_user_count = $new_users->count();
        $new_user_ids = $new_users->pluck('ac_id')->all();
        //昨日订单金额
        $orders = OrderService::getUserOrders($new_user_ids,$this->yesterdayTimestamp, $this->todayTimestamp);
        $order_amount = $orders->pluck('amount')->sum();

        $this->model->new_users = $new_user_count;
        $this->model->first_day_amount = $this->model->total_amount = $order_amount;
        //首日LTV
        $this->model->one_day_ltv = $new_user_count ? $order_amount / $new_user_count : 0;
        $this->model->save();
        //更新往日的LTV
        foreach ($this->days as $day => $ltv_key) {
            $dateTimes = [];
            $dateTimes[] = $this->yesterday;
            for ($i = 1; $i <= $day; ++$i) {
                $dateTimes[] = date('Y-m-d', $this->yesterdayTimestamp - (self::DAY_TIMESTAMP * $i));
            }
            $day += $this->gapDay;
            $ltv_yesterday = Carbon::parse($day + 1 .' days ago');
            $analyze_result = PayAnalyze::where('date_time', $ltv_yesterday->toDateString())
                ->where('type', self::STAT_TYPE_PLATFORM)->first();
            if (!$analyze_result) {
                continue;
            }
            $this->updateAnalyze($analyze_result, $dateTimes, self::STAT_TYPE_PLATFORM, $ltv_key);
        }
    }

    /**
     * 更新记录.
     *
     * @param PayAnalyze $model
     * @param array      $dateTimes
     * @param $type
     * @param string $ltv_key
     * @param null   $server_id
     * @param null   $channel_id
     */
    protected function updateAnalyze(PayAnalyze $model, array $dateTimes, $type, $ltv_key = '', $server_id = null, $channel_id = null)
    {
        $db = PayAnalyze::whereIn('date_time', $dateTimes)
            ->where('type', $type);
        if ($server_id) {
            $db->where('server_id', $server_id);
        }
        if ($channel_id) {
            $db->where('channel_id', $channel_id);
        }
        $orders = $db->get();
        if ($orders->isEmpty()) {
            $new_total_amount = 0;
        } else {
            $new_total_amount = $orders->pluck('first_day_amount')->sum();
        }

        //更新记录
        $model->total_amount = $new_total_amount;
        $user_count = $model->new_users;
        //当日LTV
        $today_ltv = $user_count ? $new_total_amount / $user_count : 0;
        $model->$ltv_key = $today_ltv;
        $model->save();
    }
}
